/*
 ModelBase.js
   Base class for all client-side model objects. "define" returns a constuctor function.
*/
define(["jquery", "appConfig", "DataException", "EORException"], function($, appConfig, DataException, EORException) {
	
	/* ModelBase Class	Constructor, called by all inheriting classes.
	 *1    
	 * @param	 name	The name by which this instance will be referenced.
	 */
	function ModelBase(name) {
		// Private Properties
		var _name	= (name) ? name : 'ModelBase';
		var _row = -1;
		var _currentTableID = -1;
		var _limit = -1;
		var _cache = [];
		var _rowUpdatedHandlers = new Array();
		var _cacheUpdatedHandlers = new Array();
		var _allowedEvents;
		
		
		// Initialize default _eventHandlers, _allowedEvents and _css arrays.
		_allowedEvents = ['loaded', 'unloaded', 'reloaded'];
		
				
		// Private Methods.
		//
		// Event Handlers.
		function dataError(jqXHR, textStatus, errorThrown) {
			throw new DataException("Server Request Error", 20000001, errorThrown, textStatus);		

		};

		/* The call to the server-side data script was (nominally) successful. Check for the presence of a status block,
		 * hanle any errors in status, assign the tables returned to the _cache array and initialize the first record.
		 */
		function dataReceived(data, textStatus, jqXHR) {
			var property;
			if (data.status.code !== 0) { 
				_lastStatus = data.status;
				throw new DataException("Server-Error in Script, No Status Block", 20000002, data.status.code + " : " + data.status.text, data.status.script); 
			}
			else {
				_lastStatus = data.status;
				_cache = new Array();
				_cache.push([]); // create at least 1 table-row in cache.
				_currentTableID = 0;  //assume there is only 1 table, for now.
				for (property in data.tables[_currentTableID].rows) {
					 if (property !== "status") {
						 // Add the object to the cache.
						 _cache[_currentTableID].push(data.tables[_currentTableID].rows[property]);
					 }
				}
				if (_cache.length === 0) {
					throw new DataException("No Data Returned", 20000003, "A positive reply was received by no data table(s) were found", "ModelBase.js");				
				}
			}
		};
		
		/*
		 *
		 */		
		function fireHandlerChain(evt, data) {
			var tempChain, key;
			
			tempChain = (evt === "rowUpdated") ? _rowUpdatedHandlers : _cacheUpdatedHandlers;
			for (key in tempChain) {
				tempChain[key](data);
			}
		};
		
		// Public Property-accessors
		ModelBase.prototype.field; // Initialize to undefined. Set to object with current row's values by the "nextRow()" method.
		ModelBase.prototype.__defineGetter__("row", function() { return _row; });
		ModelBase.prototype.__defineGetter__("name", function() { return _name; });
		ModelBase.prototype.__defineGetter__("lastStatus", function() { return _lastStatus; });
		ModelBase.prototype.__defineGetter__("count", function() { return _cache[0].length; });
		ModelBase.prototype.__defineGetter__("limit", function() { return _limit; });
		ModelBase.prototype.__defineSetter__("limit", function(x) { _limit = x; });
		ModelBase.prototype.__defineSetter__("rowUpdated", function(func) { return bind('rowUpdated', func); });
		ModelBase.prototype.__defineSetter__("cacheUpdated", function(func) { return bind('cacheUpdated', func); });



       // Public accessor allowing inheriting classes to add event types to the base. AKA a "Protected" member implementation.
		ModelBase.prototype.__defineSetter__("__events__", function(x) { _allowedEvents.push(x); });			


		////////////////////
		// Public Methods
		////////////////////
		ModelBase.prototype.rewind = function() { 
			console.log('ModelBase.rewind(), setting _row to 0.');
			_row = -1; 
	 
		};
		ModelBase.prototype.nextRow = function() { 
			var tempRow, key;
			console.log('ModelBase.nextRow()'); 
			if (((_cache) !== 'undefined') && (_cache[0].length > 0)) {
				this.field = {};
				if ((_cache[0].length-1) > _row) {
					_row++;
					tempRow = _cache[0][_row];
					//instantiate the local variables
					for (key in tempRow) {
						this.field[key] = tempRow[key];
					}
					return true;
				}
				return false;
			}
			else {
				throw new DataException("NO_CACHE_PRESENT", 20000004, "An attemt was nade to call .nextRow() on an empty recordset.", "ModelBase.js");	
			}
		};
		
		
		ModelBase.prototype.refresh = function() { console.log('ModelBase.renew()'); };
		ModelBase.prototype.fetch = function(args) { 
			var command;
			
			console.log('ModelBase.fetch()'); 
			command = appConfig.dataURL + this.name.replace('_', '/') + ".js";
			
			$.ajax({type: "POST",
					url: command,
					data: args,
					async: false, 
					dataType: 'json',
					context: this,
					success: dataReceived,
					error: dataError});

			return (_lastStatus.code) ? false : true;
			
		};

		ModelBase.prototype.newRow = function() { 
			var tempRow;
			console.log('ModelBase.newRow()');  
			if ((_cache) && (_cache[0].length > 0)) {
				this.fields = {};
				tempRow = _cache[0][0];
				//instantiate the local variables
				for (key in tempRow) {
					this.fields[key] = '';

				}				
				return true;		
			}
			else {
				this.fields;
				return false;
			}
		};
		
		ModelBase.prototype.update = function(rowID) { 
			console.log('ModelBase.update()'); 
		};
		
		ModelBase.prototype.save = function() { 
			var key;
			console.log('ModelBase.save()');
			for (key in this.field) {
				this.field[key] = '';

			}				
			
		};

		ModelBase.prototype.delete = function(rowID) { 
			console.log('ModelBase.delete()');
			
		};
	
	};
	
	/*
	 *
	 */
	ModelBase.prototype.bind = function(evt, func) {
		switch(evt) {
			case "rowUpdated":
				if (_rowUpdatedHandlers.indexOf(func) < 0) {
					_rowUpdatedHandlers.push(func);
					return true;
				}
				break;
			case "cacheUpdated":
				if (_cacheUpdatedHandlers.indexOf(func) < 0) {
					_cacheUpdatedHandlers.push(func);
					return true;
				}
				break;
			default:
				return false;
				break;
		}
		return false;
	};
	
	/*
	 *
	 */	
	ModelBase.prototype.fire = function(evt, data) {
		switch(evt) {
			case "rowUpdated":
				break;
			case "cacheUpdated":
				break;
			default:
				return false;
				break;
		}
		return false;
	};
	
	return ModelBase;
});